package com.zipou.myFax.mail;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeBodyPart;
import javax.mail.search.FlagTerm;

import com.zipou.myFax.MyFax;
import com.zipou.myFax.Exception.FileException;
import com.zipou.myFax.Exception.MailServiceException;
import com.zipou.myFax.Exception.SendingFaxException;

public class MailServiceImpl {

	private Folder folder;
	private Thread checking;

	private MyFax myfax;



	private Session session;
	private Store store;

	public MailServiceImpl(MyFax myfax) throws MailServiceException {
		try {

			this.myfax = myfax;

			// Create empty properties
			Properties props = new Properties();

			// Get session
			session = Session.getDefaultInstance(props, null);
			store = session.getStore("imaps");

			this.connect();

			checking = new ImapCheckingThread(this);

		} catch (Exception e) {
			throw new MailServiceException(
					"Impossible de creer le service de mail :" + e.getMessage());
		}
	}

	private void connect() throws MessagingException {
		// Get the store
		if (! store.isConnected()) {
			store.connect(myfax.getProperty("MAIL_HOST"),
					myfax.getProperty("MAIL_USER"),
					myfax.getProperty("MAIL_PASSWORD"));
			// Getting the Folder
			folder = store.getFolder(myfax.getProperty("MAIL_INBOX"));
			folder.open(Folder.READ_WRITE);

		}
	}

	public final void start() {
		checking.start();
	}

	private void getMultipart(Message message) throws MessagingException,
	FileException, IOException {
		// je recherche les differentes parties du message
		Multipart multipart = (Multipart) message.getContent();
		for (int i = 0, n = multipart.getCount(); i < n; i++) {
			Part part = multipart.getBodyPart(i);
			String disposition = part.getDisposition();
			// c'est un fichier ?
			if ((disposition != null)
					&& ((disposition.equals("ATTACHMENT") || (disposition
							.equals("INLINE"))))) {
				// OUI
				MimeBodyPart mbp = (MimeBodyPart) part;
				myfax.getLogger().info(
						"Part: " + mbp.getContentType() + " Disposition="
						+ disposition);
				if (mbp.isMimeType("APPLICATION/PDF")) {
					String filename = myfax.getProperty("FAX_TMP_DIRECTORY")
					+ part.getFileName();
					myfax.getLogger().info(
							"PDF OK : Envoi du fichier: " + filename);

					// J'upload
					upload(part.getInputStream(), filename);

					// je lance l'envoi.
					/**
					 * Check the directory... Hylafax need the file to be sotred
					 * in /var/spool/hylafax/
					 */
					this.sendFax(message.getSubject(),
							"tmp/" + part.getFileName());
				}
			}
		}
	}

	private void sendFax(String subject, String string) {
		try {
			myfax.getFax().sendFax(subject, string);
		} catch (SendingFaxException e) {
			myfax.getLogger().severe(
					"Unbale to Send Fax to '" + subject + "' :"
					+ e.getMessage());
		}
	}

	public final void upload(InputStream is, String loc) throws FileException {
		try {
			File file = new File(loc);
			FileOutputStream fos = new FileOutputStream(file);
			byte buf[] = new byte[1024];
			int len;
			while ((len = is.read(buf)) > 0) {
				fos.write(buf, 0, len);
			}
			fos.close();
			is.close();

		} catch (Exception e) {
			throw new FileException(" Unabel to save Attachements: "
					+ e.getMessage());
		}

	}

	public final void checkMail() throws MailServiceException {
		try {
			
			this.connect();
			Message messages[] = folder.search(new FlagTerm(new Flags(
					Flags.Flag.SEEN), false));

			for (Message m : messages) {
				m.setFlags(new Flags(Flags.Flag.SEEN), true);
				myfax.getLogger().info(
						" Mail from : " + m.getFrom()[0] + "\t Subject ="
						+ m.getSubject());
				getMultipart(m);
			}
		} catch (MessagingException e) {
			throw new MailServiceException(
					"Unable to Check Mail because of a MessagingException "
					+ e.getMessage());
		} catch (IOException e) {
			throw new MailServiceException(
					"InputOutput Exception on MailService: " + e.getMessage());
		} catch (FileException e) {
			throw new MailServiceException("FileException in MailService: "
					+ e.getMessage());
		} 
	}
	
	public MyFax getMyfax() {
		return myfax;
	}

	public void setMyfax(MyFax myfax) {
		this.myfax = myfax;
	}
}
